﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace GingerBeard.Utilities
{
	public class Matrix
	{
		private Vector xAxis = new Vector();
		public GingerBeard.Utilities.Vector XAxis
		{
			get { return xAxis; }
			set { xAxis = value; }
		}
		private Vector yAxis = new Vector();
		public GingerBeard.Utilities.Vector YAxis
		{
			get { return yAxis; }
			set { yAxis = value; }
		}
		private Vector zAxis = new Vector();
		public GingerBeard.Utilities.Vector ZAxis
		{
			get { return zAxis; }
			set { zAxis = value; }
		}
		private Vector translation = new Vector();
		public GingerBeard.Utilities.Vector Translation
		{
			get { return translation; }
			set { translation = value; }
		}
		public Matrix()
		{
		}

		public Matrix(Vector x, Vector y, Vector z, Vector t)
		{
			xAxis = x;
			yAxis = y;
			zAxis = z;
			translation = t;
		}

		public void Set(float m1, float m2, float m3, float m4, float m5, float m6, float m7, float m8, float m9, float m10, float m11, float m12, float m13, float m14, float m15, float m16)
		{
			xAxis.Set(m1, m2, m3, m4);
			yAxis.Set(m5, m6, m7, m8);
			zAxis.Set(m9, m10, m11, m12);
			translation.Set(m13, m14, m15, m16);
		}

		public void SetIdentity()
		{
			xAxis.Set(Vector.XAxis.GetXYZ_W0());
			yAxis.Set(Vector.WAxis.GetXYZ_W0());
			zAxis.Set(Vector.ZAxis.GetXYZ_W0());
			translation.Set(Vector.WAxis.GetXYZ_W0());
		}

		public Vector Transform(Vector v)
		{
			return xAxis.Scale(v.Get(0)) + yAxis.Scale(v.Get(1)) + zAxis.Scale(v.Get(2)) + translation.Scale(v.Get(3));
		}

		public Matrix PreMultiply(Matrix m)
		{
			return new Matrix(
				m.Transform(xAxis),
				m.Transform(yAxis),
				m.Transform(zAxis),
				m.Transform(translation));
		}

		public Matrix PostMultiply(Matrix m)
		{
			return m.PreMultiply(this);
		}

		public void SetRotX(float angle)
		{
			float c = (float)Math.Cos(angle);
			float s = (float)Math.Sin(angle);
			xAxis.Set(Vector.XAxis.GetXYZ_W0());
			yAxis.Set(0,c,s,0);
			zAxis.Set(0,-s,c,0);
			translation.Set(Vector.WAxis);
		}

		public void SetRotY(float angle)
		{
			float c = (float)Math.Cos(angle);
			float s = (float)Math.Sin(angle);
			xAxis.Set(c,0,-s,0);
			yAxis.Set(Vector.YAxis.GetXYZ_W0());
			zAxis.Set(s, 0, c, 0);
			translation.Set(Vector.WAxis);
		}

		public void SetRotZ(float angle)
		{
			float c = (float)Math.Cos(angle);
			float s = (float)Math.Sin(angle);
			xAxis.Set(c,s,0,0);
			yAxis.Set(-s,c,0,0);
			zAxis.Set(Vector.ZAxis.GetXYZ_W0());
			translation.Set(Vector.WAxis);
		}
	}
}
